#include "networktest.h"
#include "ui_networktest.h"

NetWorkTest::NetWorkTest(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::NetWorkTest)
{
    ui->setupUi(this);
    tcpServer = new QTcpServer(this);
    tcpSockect = new QTcpSocket(this);
    udpSockect = new QUdpSocket(this);
    this->setAllLocalIP();
    this->setModeUI();
    ui->textHostIP->setText(ui->cbLocalIP->currentText());
    ui->textPortHost->setText("12345");
    ui->textPortLocal->setText("23456");
    this->setConnectIcon(false);
    connect(ui->cbMode,SIGNAL(currentIndexChanged(int)),this,SLOT(slot_cbModeChanged()));
}

NetWorkTest::~NetWorkTest()
{
    delete ui;
}

void NetWorkTest::setAllLocalIP()
{
    QString addr;
    QList<QHostAddress> addrList = QNetworkInterface::allAddresses();
    // use the first non-localhost IPv4 address
    for (int i = 0 ; i < addrList.size(); ++i)
    {
        if (addrList.at(i) != QHostAddress::LocalHost && addrList.at(i).toIPv4Address())
        {
            addr = addrList.at(i).toString();
            ui->cbLocalIP->addItem(addr);
        }
    }
}

int NetWorkTest::tcpServerInit()
{
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(slot_tcpServer_newConnection()));
    if( tcpServer->listen(QHostAddress::Any,ui->textPortLocal->text().toUInt()) != true)
    {
        QMessageBox::warning(this,"Warning","Port listen Failed!");
        return -1;
    }
    return 0;
}
int NetWorkTest::tcpClientInit()
{
    QHostAddress addr;
    addr.setAddress(ui->textHostIP->text());
    tcpSockect->connectToHost(addr,ui->textPortHost->text().toUInt());
    connect(tcpSockect,SIGNAL(connected()),this,SLOT(slot_tcpClient_Connected()));
    connect(tcpSockect,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_tcpSocketErr()));
    return 0;
}

int NetWorkTest::udpInit()
{
    quint16 port;
    QHostAddress addr;
    addr.setAddress(ui->cbLocalIP->currentText());
    port = ui->textPortLocal->text().toUInt();
    while( udpSockect->bind(addr,port) != true )
    {
        QMessageBox::warning(this,"Warning","Port bind failed!");
        return -1;
    }
    if(udpSockect->state() != QUdpSocket::BoundState)
    {
        QMessageBox::warning(this,"Warning","UDP isn't BoundState!");
    }
    QMessageBox::information(this,"Info","Port bind sucess!");
    connect(udpSockect,SIGNAL(readyRead()),this,SLOT(slot_udp_readyRead()));
    connect(udpSockect,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_udpSocketErr()));
    this->setConnectIcon(true);
    return 0;
}



void NetWorkTest::tcpServerClose()
{
    tcpSockect->close();
    tcpServer->close();
    disconnect(tcpSockect,SIGNAL(readyRead()),this,SLOT(slot_tcp_readyRead()));
    disconnect(tcpSockect,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_tcpSocketErr()));
    this->setConnectIcon(false);
}
void NetWorkTest::tcpClientClose()
{
    tcpSockect->close();
    disconnect(tcpSockect,SIGNAL(connected()),this,SLOT(slot_tcpClient_Connected()));
    disconnect(tcpSockect,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_tcpSocketErr()));
    this->setConnectIcon(false);
}
void NetWorkTest::udpClose()
{
    udpSockect->close();
    disconnect(udpSockect,SIGNAL(readyRead()),this,SLOT(slot_udp_readyRead()));
    disconnect(udpSockect,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_udpSocketErr()));
    this->setConnectIcon(false);
}

int NetWorkTest::on_btOpen_clicked()
{
    //点击Open 获取设置的参数 并初始化
    int ret;
    ui->btOpen->setDisabled(true);
    ui->btClose->setEnabled(true);
    ui->cbMode->setDisabled(true);
    ui->cbLocalIP->setDisabled(true);
    ui->textHostIP->setReadOnly(true);
    ui->textPortHost->setReadOnly(true);
    ui->textPortLocal->setReadOnly(true);
    if(ui->textPortHost->text().toUInt() > 65535)
    {
        QMessageBox::warning(this,"Warning","Port Setting Wrong!");
        return  -1;
    }
    if(ui->cbMode->currentText() == "TCP Server") ret = this->tcpServerInit();//TCP Server
    else if(ui->cbMode->currentText() == "TCP Client")ret = this->tcpClientInit();//TCP Client
    else ret = this->udpInit(); //UDP
    if(!ret) return 0;
    else
    {
        if(this->connected == false) QMessageBox::warning(this,"Warning","Connect failed!");
        else QMessageBox::warning(this,"Warning","Already connected!");
        return -1;
    }
}

int NetWorkTest::on_btClose_clicked()
{
    //点击Close 关闭连接
    ui->btOpen->setEnabled(true);
    ui->btClose->setDisabled(true);
    ui->cbMode->setEnabled(true);
    ui->cbLocalIP->setEnabled(true);
    ui->textHostIP->setReadOnly(false);
    ui->textPortHost->setReadOnly(false);
    ui->textPortLocal->setReadOnly(false);
    if (this->connected == false)
    {
        QMessageBox::warning(this,"Warning","Not connected!");
        return -1;
    }
    if(ui->cbMode->currentText() == "TCP Server")this->tcpServerClose();        //TCP Server
    else if(ui->cbMode->currentText() == "TCP Client") this->tcpClientClose();  //TCP Client
    else this->udpClose();//UDP
    return 0;
}

int NetWorkTest::on_btSend_clicked()
{
    //点击发送 输入框中的文本发送
    if (this->connected == false)
    {
        QMessageBox::warning(this,"Warning","Not connected!");
        return -1;
    }
    if(this->connected != true) return -1;
    if(ui->cbMode->currentText() == "UDP") this->udpSend();//UDP
    else this->tcpSend();//TCP
    return 0;
}

void NetWorkTest::tcpSend()
{
    QByteArray data;
    data = ui->textSend->toPlainText().toLocal8Bit().data();
    tcpSockect->write(data);
}

void NetWorkTest::udpSend()
{
    QHostAddress addr;
    quint16 port;
    QNetworkDatagram *data;
    QByteArray tmp;
    port = ui->textPortHost->text().toUInt();
    addr.setAddress(ui->textHostIP->text());
    tmp.setRawData(ui->textSend->toPlainText().toLocal8Bit().data(),ui->textSend->toPlainText().size());
    data = new QNetworkDatagram(tmp,addr,port);
    udpSockect->writeDatagram(*data);
    delete data;
}
void NetWorkTest::slot_tcpServer_newConnection()
{
    this->setConnectIcon(true);
    tcpSockect = tcpServer->nextPendingConnection();
    connect(tcpSockect,SIGNAL(readyRead()),this,SLOT(slot_tcp_readyRead()));
    connect(tcpSockect,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_tcpSocketErr()));
}

void NetWorkTest::slot_tcp_readyRead()
{
    QString buf;
    buf = tcpSockect->readAll();
    ui->textRecv->appendPlainText(buf);
}

void NetWorkTest::slot_tcpClient_Connected()
{
    QMessageBox::information(this,"Info","connected!");
    this->setConnectIcon(true);
    connect(tcpSockect,SIGNAL(readyRead()),this,SLOT(slot_tcp_readyRead()));
}

void NetWorkTest::slot_udp_readyRead()
{
    QString *buf;
    char *tmp;
    quint64 size;
    QHostAddress addr;
    quint16 port;
    while(udpSockect->hasPendingDatagrams())
    {
        size = udpSockect->pendingDatagramSize();
        tmp =  new char(size);
        udpSockect->readDatagram(tmp,size,&addr,&port);
        buf = new QString(QByteArray(tmp,size));
        ui->textRecv->appendPlainText(*buf);
        delete tmp;
        delete buf;
    }
}
void NetWorkTest::setModeUI()
{
    if(ui->cbMode->currentText() == "UDP")
    {//UDP
        ui->textHostIP->setEnabled(true);
        ui->textPortHost->setEnabled(true);
        ui->textPortLocal->setEnabled(true);
    }
    else
    {
        ui->cbMode->setEnabled(true);
        if(ui->cbMode->currentText() == "TCP Server")
        {//TCP Server
            ui->textHostIP->setDisabled(true);
            ui->textPortHost->setDisabled(true);
            ui->textPortLocal->setEnabled(true);
        }
        else
        {//TCP Client
            ui->textHostIP->setEnabled(true);
            ui->textPortHost->setEnabled(true);
            ui->textPortLocal->setDisabled(true);
        }
    }

}

void NetWorkTest::slot_cbModeChanged()
{
    this->setModeUI();
}

void NetWorkTest::setConnectIcon()
{
    if(this->connected) ui->connectStatus->setPixmap(QPixmap(":/connected.png").scaled(ui->connectStatus->width(),ui->connectStatus->height(),Qt::KeepAspectRatio));
    else ui->connectStatus->setPixmap(QPixmap(":/disconnected.png").scaled(ui->connectStatus->width(),ui->connectStatus->height(),Qt::KeepAspectRatio));
}

void NetWorkTest::slot_tcpSocketErr()
{
    QMessageBox::critical(this,"Error",tcpSockect->errorString());
    if(this->connected == true) this->on_btClose_clicked();
}
void NetWorkTest::slot_udpSocketErr()
{
    QMessageBox::critical(this,"Error",udpSockect->errorString());
    if (this->connected == true) this->on_btClose_clicked();
}

void NetWorkTest::setConnectIcon(bool a)
{
    this->connected = a;
    this->setConnectIcon();
}
